
/**********************************************   头文件   *********************************************** */


#include "freertos_demo.h"

/* FreeRTOS相关头文件 */
#include "FreeRTOS.h"
#include "task.h"

/* 需要用到的其他头文件 */
#include "key.h"
#include "led.h"
#include "usart.h"

/*********************************************   任务配置   *********************************************** */

/* 启动任务的配置*/
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handler;


/* 任务1的配置*/
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handler;

/* 任务2的配置*/
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handler;




/* 任务3的配置*/
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handler;


/*********************************************   任务函数声明   *********************************************** */

void start_task(void *pvParameters);
void task1(void *pvParameters);
void task2(void *pvParameters);
void task3(void *pvParameters);


/*********************************************   freertos入口   *********************************************** */


/**
 * freertos的入口函数，启动FreeRTOS
 * @param
 * @param
 * ...
 * @return
 */
void freerttos_start(void)
{
    /* 1.创建启动任务 */
    xTaskCreate(
        (TaskFunction_t)start_task,               // 任务函数地址
        (char *)"start_task",                     // 任务名字
        (configSTACK_DEPTH_TYPE)START_TASK_STACK, // 任务栈大小，默认最小128
        (void *)NULL,                             // 传递给任务的参数
        (UBaseType_t)START_TASK_PRIORITY,         // 任务优先级
        (TaskHandle_t *)&start_task_handler);     // 任务句柄地址
    /* 2.开启任务调度器; 会自动创建空闲任务 */
    vTaskStartScheduler();
}


/*********************************************   任务函数   *********************************************** */


/**
 * 启动任务，用于创建其他任务
 * @param
 * @param
 * ...
 * @return
 */
void start_task(void *pvParameters)
{
    /* 进入临界区 */
    taskENTER_CRITICAL();

    /* 创建任务1 */
    xTaskCreate(
        (TaskFunction_t)task1,
        (char *)"task1",
        (configSTACK_DEPTH_TYPE)TASK1_STACK,
        (void *)NULL,
        (UBaseType_t)TASK1_PRIORITY,
        (TaskHandle_t *)&task1_handler);

    /* 创建任务2 */
    xTaskCreate(
        (TaskFunction_t)task2,
        (char *)"task2",
        (configSTACK_DEPTH_TYPE)TASK2_STACK,
        (void *)NULL,
        (UBaseType_t)TASK2_PRIORITY,
        (TaskHandle_t *)&task2_handler);

    /* 创建任务3 */
    xTaskCreate(
        (TaskFunction_t)task3,
        (char *)"task3",
        (configSTACK_DEPTH_TYPE)TASK3_STACK,
        (void *)NULL,
        (UBaseType_t)TASK3_PRIORITY,
        (TaskHandle_t *)&task3_handler);

    /* 删除启动任务（自身），启动任务只需要执行一次即可 */
    vTaskDelete(NULL);

    /* 退出临界区 */
    taskEXIT_CRITICAL();
}

/**
 * 任务一，实现LED1每500ms闪烁一次
 * @param
 * @param
 * ...
 * @return
 */
void task1(void *pvParameters)
{
    while (1)
    {
        printf("task1运行...\r\n");
        LED_Toggle(LED1_GPIO_Port, LED1_Pin);
        vTaskDelay(500);
    }
}

/**
 * 任务二，实现LED2每500ms闪烁一次
 * @param
 * @param
 * ...
 * @return
 */
void task2(void *pvParameters)
{
    while (1)
    {
        printf("task2运行...\r\n");
        LED_Toggle(LED2_GPIO_Port, LED2_Pin);
        vTaskDelay(500);
    }
}

/**
 * 任务三，判断KEY1是否按下，按下删除任务一
 * @param
 * @param
 * ...
 * @return
 */
void task3(void *pvParameters)
{
    uint8_t key = 0;
    while (1)
    {
        printf("task3运行...\r\n");
        key = Key_Scan();
        if (key == KEY1_PRESS)
        {
            /* KEY1按下挂起任务1 */
            vTaskSuspend(task1_handler);
        }
        else if(key == KEY2_PRESS)
        {
            /* KEY2按下恢复任务1 */
            vTaskResume(task1_handler);
        }
        vTaskDelay(500);
    }
}
